package top.iwife.httpclient;

import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import top.iwife.httpclient.model.HttpRequestHeader;
import top.iwife.httpclient.model.HttpRequestOption;
import top.iwife.httpclient.model.HttpRequestParam;
import top.iwife.httpclient.model.HttpResponse;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.List;

/**
 * Author 张杰
 * CreateTime 2021/11/17
 * <p>
 * http请求工具类
 */
public class HttpClient {
    /**
     * 目前只封装了get和post，因为当前项目只用到了get和post。
     *
     * @param option 请求参数
     * @return 自定义响应体
     */
    public static HttpResponse execute(final HttpRequestOption option) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpRequestBase httpRequestBase = null;
        switch (option.getMethod()) {
            case GET:
                try {
                    URIBuilder uriBuilder = new URIBuilder(option.getUrl());
                    // 添加参数
                    List<HttpRequestParam> httpRequestParams = option.getParams();
                    if (httpRequestParams != null && httpRequestParams.size() > 0) {
                        for (HttpRequestParam httpRequestParam : httpRequestParams) {
                            uriBuilder.addParameter(httpRequestParam.getName(), httpRequestParam.getValue());
                        }
                    }
                    httpRequestBase = new HttpGet(uriBuilder.build());
                } catch (URISyntaxException e) {
                    return new HttpResponse(HttpStatus.SC_NOT_FOUND, e.getMessage());
                }
                break;
            case POST:
                HttpPost tempHttpPost = new HttpPost(option.getUrl());
                byte[] body = option.getBody();
                // 添加body
                if (body != null) {
                    tempHttpPost.setEntity(new ByteArrayEntity(body));
                }
                httpRequestBase = tempHttpPost;
                break;
        }

        List<HttpRequestHeader> httpRequestHeaders = option.getHeaders();
        // 有header
        if (httpRequestHeaders != null && httpRequestHeaders.size() > 0) {
            for (HttpRequestHeader httpRequestHeader : httpRequestHeaders) {
                httpRequestBase.addHeader(httpRequestHeader.getName(), httpRequestHeader.getValue());
            }
        }
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(5000)
                .setConnectTimeout(5000)
                .setSocketTimeout(5000)
                .build();
        httpRequestBase.setConfig(requestConfig);
        try {
            CloseableHttpResponse response = httpClient.execute(httpRequestBase);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 读取响应体字节流
                InputStream is = response.getEntity().getContent();
                final int bufSize = 8192;
                byte[] buffer = new byte[bufSize];
                ByteArrayOutputStream os = new ByteArrayOutputStream(bufSize);
                int n;
                while ((n = is.read(buffer)) != -1) {
                    os.write(buffer, 0, n);
                    os.flush();
                }
                is.close();
                os.close();
                // 成功态
                return new HttpResponse(
                        response.getStatusLine().getStatusCode(),
                        response.getStatusLine().getReasonPhrase(),
                        os.toByteArray()
                );
            }
            // 远程服务器的其他错误
            return new HttpResponse(response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase());
        } catch (IOException e) {
            // 本机异常错误
            return new HttpResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }
}
